package com.wml.client;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.json.JSONException;
import org.json.JSONObject;

import com.wml.client.domain.FileInfo;
import com.wml.client.domain.RemoteFile;
import com.wml.client.https.ClientFileHttpUploads;
import com.wml.client.https.ClientFileHttpUploads.ProgressHandle;
import com.wml.client.https.FileUtils;
import com.wml.client.https.HttpUtils;
import com.wml.client.https.PasteBase64Img;

/**
 * wdap客户端服务类
 * 
 * @author macpl
 *
 */
public class WmlFilesClient {
	private String operatorPassword;
	private String operatorLoginname;
	private String secret;
	private String baseUrl;
	@SuppressWarnings("unused")
	private static final Logger log = Logger.getLogger(WmlFilesClient.class);

	public static WmlFilesClient getInstance(String operatorPassword, String operatorLoginname, String secret,
			String serviceUrl) {
		WmlFilesClient obj = new WmlFilesClient();
		obj.operatorPassword = operatorPassword;
		obj.operatorLoginname = operatorLoginname;
		obj.secret = secret;
		obj.baseUrl = serviceUrl;
		return obj;
	}

	private void validResult(JSONObject obj) throws RemoteException, JSONException {
		if (obj.get("STATE").toString().equals("1")) {
			throw new RemoteException(obj.get("MESSAGE").toString());
		}
	}

	/**
	 * 获得一个远程的虚拟文件
	 * 
	 * @param filename 文件名称，带扩展名
	 * @param filesize 文件大小
	 * @return
	 * @throws RemoteException
	 * @throws JSONException
	 */
	public RemoteFile initFile(String filename, long filesize, String appid) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("filename", filename);
		data.put("length", Long.toString(filesize));
		data.put("appid", appid);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/fileapi/file/init.do", data);
		validResult(obj);
		RemoteFile rfile = new RemoteFile();
		rfile.setId(obj.get("fileid").toString());
		rfile.setPath(obj.get("realpath").toString());
		return rfile;
	}

	/**
	 * 保存一个文件到磁盘
	 * 
	 * @param file
	 * @param path
	 */
	public void saveFile(File file, RemoteFile remoteFile, String fileUpdataProcessKey) {
		FileUtils.copyFile(file, new File(remoteFile.getPath()), fileUpdataProcessKey);
	}

	/**
	 * 上传一个文件到远程WDAP
	 * 
	 * @param file
	 * @param filename
	 * @param wdapFileid
	 * @param fileUpdataProcessKey
	 * @param handle
	 * @throws IOException
	 */
	public void uploadFile(File file, String filename, String wdapFileid, String fileUpdataProcessKey,
			ClientFileHttpUploads.ProgressHandle handle) throws IOException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("fileid", wdapFileid);
		data.put("processkey", fileUpdataProcessKey);
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		ClientFileHttpUploads uploader = ClientFileHttpUploads.getInstance(baseUrl.trim() + "/fileapi/file/upload.do",
				data);
		uploader.setRemoteProgressUrl(baseUrl.trim() + "/fileapi/file/process.do");
		uploader.setProgressHandle(handle);
		uploader.doUpload(file, filename);
	}

	/**
	 * 上传一个文件到远程WDAP
	 * 
	 * @param rfileid  可空，远程附件id，非空时更新，为空时创建
	 * @param text     内容
	 * @param filename 文件名称，如“标题.json”
	 * @param appid    业务id，可空
	 * @return
	 * @throws IOException
	 */
	public String uploadTextFile(String rfileid, String text, String filename, String appid) throws IOException {
		byte[] datas = text.getBytes("UTF-8");
		if (StringUtils.isBlank(rfileid)) {
			RemoteFile rfile = initFile(filename, datas.length, appid);
			rfileid = rfile.getId();
		}
		Map<String, String> data = new HashMap<String, String>();
		data.put("fileid", rfileid);
		// data.put("processkey", fileUpdataProcessKey);
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		ClientFileHttpUploads uploader = ClientFileHttpUploads.getInstance(baseUrl.trim() + "/fileapi/file/upload.do",
				data);
		uploader.setRemoteProgressUrl(baseUrl.trim() + "/fileapi/file/process.do");
		// uploader.setProgressHandle(handle);
		uploader.doUpload(filename, datas.length, new ByteArrayInputStream(datas));
		return rfileid;
	}

	/**
	 * 保存一个文件到磁盘
	 * 
	 * @param file
	 * @param path
	 */
	public void saveFile(InputStream inStream, RemoteFile remoteFile) {
		FileUtils.saveFile(inStream, new File(remoteFile.getPath()));
	}

	/**
	 * 保存一个文件到磁盘
	 * 
	 * @param file
	 * @param path
	 */
	public void saveFile(byte[] byteArray, RemoteFile remoteFile) {
		FileUtils.saveFile(byteArray, new File(remoteFile.getPath()));
	}

	/**
	 * 保存一个文件到磁盘
	 * 
	 * @param file
	 * @param path
	 */
	public void saveFile(String base64, RemoteFile remoteFile) {
		PasteBase64Img data = new PasteBase64Img(base64);
		FileUtils.saveFile(data.getData(), new File(remoteFile.getPath()));
	}

	/**
	 * 保存一个网页为pdf文件
	 * 
	 * @param pageUrl    html頁面地址
	 * @param remoteFile 保存到的遠程文件
	 * @param watertitle 水印信息
	 * @throws RemoteException
	 * @throws JSONException
	 */
	public void saveFileByUrlPage(String pageUrl, RemoteFile remoteFile, String watertitle)
			throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("pageurl", pageUrl);
		data.put("processkey", remoteFile.getId());
		data.put("fileid", remoteFile.getId());
		if (StringUtils.isNotBlank(watertitle)) {
			data.put("watertitle", watertitle);
		}
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/fileapi/file/urlpage.do", data);
		validResult(obj);
	}

	/**
	 * 提交一個臨時文件為持久化
	 * 
	 * @param fileId
	 * @throws JSONException
	 * @throws RemoteException
	 */
	public void submitFile(String fileId) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("fileid", fileId);
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/fileapi/file/submit.do", data);
		validResult(obj);
	}

	/**
	 * 提交一個臨時文件為持久化
	 * 
	 * @param fileId
	 * @throws JSONException
	 * @throws RemoteException
	 */
	public Map<String, Object> getPropertys() throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/fileapi/file/property.do", data);
		Map<String, Object> map = new HashMap<String, Object>();
		validResult(obj);
		map.put("FILESIZE", obj.getJSONObject("DATA").getLong("FILESIZE"));
		map.put("IMGSIZE", obj.getJSONObject("DATA").getLong("IMGSIZE"));
		map.put("FILETYPE", obj.getJSONObject("DATA").getString("FILETYPE"));
		map.put("IMGTYPE", obj.getJSONObject("DATA").getString("IMGTYPE"));
		map.put("MEDIATYPE", obj.getJSONObject("DATA").getString("MEDIATYPE"));
		return map;
	}

	/**
	 * 將持久化文件釋放為臨時文件
	 * 
	 * @param fileId
	 * @throws RemoteException
	 * @throws JSONException
	 */
	public void freeFile(String fileId) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("fileid", fileId);
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/fileapi/file/free.do", data);
		validResult(obj);
	}

	/**
	 * 邏輯刪除文件
	 * 
	 * @param fileId
	 * @throws RemoteException
	 * @throws JSONException
	 */
	public void delFile(String fileId) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("fileid", fileId);
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/fileapi/file/del.do", data);
		validResult(obj);
	}

	/**
	 * 获得下載地址
	 * 
	 * @param id
	 * @return
	 * @throws JSONException
	 * @throws RemoteException
	 */
	public String getFileDownloadUrl(String fileId) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("fileid", fileId);
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/fileapi/url/download.do", data);
		validResult(obj);
		return obj.get("url").toString();
	}

	/**
	 * 获得转换日志地址
	 * 
	 * @param fileId
	 * @return
	 * @throws JSONException
	 * @throws RemoteException
	 */
	public String getConvetLogUrl(String fileId) throws RemoteException, JSONException {
		return "include/Pubtasks.do?fileid=" + fileId;
	}

	/**
	 * 获得播放地址
	 * 
	 * @param id
	 * @return
	 * @throws JSONException
	 * @throws RemoteException
	 */
	public String getFilePlayUrl(String fileId) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("fileid", fileId);
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/fileapi/url/play.do", data);
		validResult(obj);
		return obj.get("url").toString();
	}

	/**
	 * 获得文件预览地址
	 * 
	 * @param fileAppId
	 * @return
	 * @throws RemoteException
	 * @throws JSONException
	 */
	public String getFileViewUrl(String fileAppId, String waterinfo) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("fileAppId", fileAppId);
		data.put("waterinfo", waterinfo);
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/viewapi/url/view.do", data);
		validResult(obj);
		return obj.get("url").toString();
	}

	/**
	 * 获得临时ID（文件id或docview的ID）
	 * 
	 * @param fileAppId
	 * @return
	 * @throws RemoteException
	 * @throws JSONException
	 */
	public String getTempId(String realid) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("id", realid);
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/viewapi/id/temp.do", data);
		validResult(obj);
		return obj.get("DATA").toString();
	}

	/**
	 * 獲得圖標地址
	 * 
	 * @param id
	 * @return
	 * @throws JSONException
	 * @throws RemoteException
	 */
	public String getFileIconUrl(String fileId) throws RemoteException, JSONException {
		return getFileIconUrl(fileId, null);
	}

	/**
	 * 獲得圖標地址
	 * 
	 * @param fileId 附件id 可空 fileid或appid必填
	 * @param appid  附件appid 可空 fileid或appid必填
	 * @param modle  图标模式 1：横向A4比例、2：纵向A4比例，选填
	 * @return
	 * @throws RemoteException
	 * @throws JSONException
	 */
	public String getFileIconUrl(String fileId, String appid) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("fileid", fileId);
		data.put("appid", appid);
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/fileapi/url/icon.do", data);
		validResult(obj);
		return obj.get("url").toString();
	}

	public FileInfo getFileInfo(String fileId) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("fileid", fileId);
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/fileapi/file/info.do", data);
		validResult(obj);
		FileInfo info = new FileInfo();
		info.setDownloadUrl(getJsonString(obj, "info|downloadUrl"));
		info.setDownNum(getJsonInt(obj, "info|visit|downum"));
		info.setExname(getJsonString(obj, "info|file|exname"));
		info.setFilesize(getJsonInt(obj, "info|file|filesize"));
		info.setIconUrl(getJsonString(obj, "info|iconUrl"));
		info.setId(getJsonString(obj, "info|file|id"));
		info.setModellabel(getJsonString(obj, "info|modellabel"));
		info.setRealpath(getJsonString(obj, "info|realpath"));
		info.setSizelabel(getJsonString(obj, "info|sizelabel"));
		info.setStatelabel(getJsonString(obj, "info|statelabel"));
		info.setViewNum(getJsonInt(obj, "info|visit|viewnum"));
		info.setTitle(getJsonString(obj, "info|file|title"));
		info.setViewUrl(getJsonString(obj, "info|viewUrl"));
		info.setSecret(getJsonString(obj, "info|file|secret"));
		return info;
	}

	private String getJsonString(JSONObject obj, String path) {
		String[] keys = path.split("\\|");
		JSONObject cobj = obj;
		if (keys.length > 1) {
			for (int n = 0; n <= keys.length - 2; n++) {
				if (cobj.isNull(keys[n])) {
					return null;
				} else {
					cobj = cobj.getJSONObject(keys[n]);
				}
			}
		}
		if (!cobj.isNull(keys[keys.length - 1])) {
			return cobj.getString(keys[keys.length - 1]);
		} else {
			return null;
		}
	}

	private int getJsonInt(JSONObject obj, String path) {
		String[] keys = path.split("\\|");
		JSONObject cobj = obj;
		if (keys.length > 1) {
			for (int n = 0; n <= keys.length - 2; n++) {
				if (cobj.isNull(keys[n])) {
					return 0;
				} else {
					cobj = cobj.getJSONObject(keys[n]);
				}
			}
		}
		if (!cobj.isNull(keys[keys.length - 1])) {
			return cobj.getInt(keys[keys.length - 1]);
		} else {
			return 0;
		}
	}

	/**
	 * 生成预览文件(可以重新生成)
	 * 
	 * @param fileId
	 * @throws RemoteException
	 * @throws JSONException
	 */
	public void generateViewFile(String fileId) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("fileid", fileId);
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/viewapi/generate.do", data);
		validResult(obj);
	}

	/**
	 * 获得附件id
	 * 
	 * @param name
	 * @param password
	 * @return
	 */
	public String getfileid(String appid) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("appid", appid);
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/fileapi/appid/tofileid.do", data);
		validResult(obj);
		if (obj.isNull("DATA")) {
			return null;
		} else {
			return obj.getString("DATA");
		}
	}

	/**
	 * 获得附件状态
	 * 
	 * @param fileAppId
	 * @return
	 * @throws JSONException
	 * @throws RemoteException
	 */
	public String getfileState(String appid) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("appid", appid);
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/fileapi/appid/tofileid.do", data);
		validResult(obj);
		if (obj.isNull("FILESTATE")) {
			return null;
		} else {
			return obj.getString("FILESTATE");
		}
	}

	/**
	 * 是否支持预览（能否生成预览文件）
	 * 
	 * @param fileAppId
	 * @return
	 * @throws JSONException
	 * @throws RemoteException
	 */
	public boolean isConvertAble(String exname, long lenght) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("exname", exname);
		data.put("lenght", Long.toString(lenght));
		data.put("operatorLoginname", operatorLoginname);
		data.put("operatorPassword", operatorPassword);
		data.put("secret", secret);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/viewapi/convert/able.do", data);
		validResult(obj);
		if (obj.getBoolean("DATA")) {
			return true;
		} else {
			return false;
		}
	}

	public String getOperatorPassword() {
		return operatorPassword;
	}

	public void setOperatorPassword(String operatorPassword) {
		this.operatorPassword = operatorPassword;
	}

	public String getOperatorLoginname() {
		return operatorLoginname;
	}

	public void setOperatorLoginname(String operatorLoginname) {
		this.operatorLoginname = operatorLoginname;
	}

	public String getSecret() {
		return secret;
	}

	public void setSecret(String secret) {
		this.secret = secret;
	}

	public String getBaseUrl() {
		return baseUrl;
	}

	public void setBaseUrl(String baseUrl) {
		this.baseUrl = baseUrl;
	}

	/**
	 * 獲取和處理远程处理进度信息
	 * 
	 * @param processKey
	 * @param progressHandle
	 * @throws RemoteException
	 * @throws JSONException
	 * @throws InterruptedException
	 */
	public void runProcessHandle(String processKey, ProgressHandle progressHandle)
			throws RemoteException, JSONException, InterruptedException {
		while (true) {
			Map<String, String> data = new HashMap<String, String>();
			data.put("processkey", processKey);
			JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/fileapi/file/process.do", data);
			validResult(obj);
			int process = getJsonInt(obj, "PROCESS");
			// state 0开始上传，1远程处理中，2全部完成
			String state = "1";
			if (process >= 100) {
				state = "2";
			}
			progressHandle.handle(process, 100, process, state);
			Thread.sleep(500);
			if (state.equals("2")) {
				break;
			}
		}
	}

	/**
	 * 获得文件上传进度
	 * 
	 * @param processkey
	 * @return
	 * @throws RemoteException
	 * @throws JSONException
	 */
	public int getUoloadProcess(String processkey) throws RemoteException, JSONException {
		Map<String, String> data = new HashMap<String, String>();
		data.put("processkey", processkey);
		JSONObject obj = HttpUtils.httpPost(baseUrl.trim() + "/fileapi/file/process.do", data);
		validResult(obj);
		return (Integer) obj.get("PROCESS");
	}

	public String getFileString(String rfileid) throws JSONException, IOException {

		ByteArrayOutputStream outputStream = null;
		InputStream is = null;
		try {
			// 构造URL
			URL url = new URL(baseUrl + "/" + getFileDownloadUrl(rfileid));
			// 打开连接
			URLConnection con = url.openConnection();
			// 输入流
			is = con.getInputStream();
			// 1K的数据缓冲
			byte[] bs = new byte[1024];
			// 读取到的数据长度
			int len;
			outputStream = new ByteArrayOutputStream();// 输出流
			// 开始读取
			while ((len = is.read(bs)) != -1) {
				outputStream.write(bs, 0, len);// 将读到的字节写入输出流
			}

			return outputStream.toString("utf-8");
		} catch (IOException e) {
			throw e;
		} finally {
			// 完毕，关闭所有链接
			if (outputStream != null)
				outputStream.close();
			if (is != null)
				is.close();
		}
	}

}
